package com.wstuo.common.security.action;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import sun.misc.BASE64Decoder;

import com.wstuo.common.security.dao.IOrganizationDAO;
import com.wstuo.common.security.dao.IUserDAO;
import com.wstuo.common.security.entity.Organization;
import com.wstuo.common.security.entity.User;
import com.wstuo.common.security.enums.SessionName;
import com.wstuo.common.security.service.IOnlineUserService;
import com.wstuo.common.security.service.IUserInfoService;
import com.wstuo.md5.service.ICopyrightMD5Service;
import com.wstuo.multitenancy.TenantIdResolver;

/**
 * 用户验证成功回调
 * @author Administrator
 *
 */
public class LoginHandler implements AuthenticationSuccessHandler {
	private static final Logger LOGGER = Logger.getLogger(LoginHandler.class ); 
	@Autowired
	private IUserDAO userDAO;
	@Autowired
	private IUserInfoService userInfoService;
	@Autowired
	private IOrganizationDAO organizationDAO;
	@Autowired
	private IOnlineUserService onlineUserService;
	@Autowired
	private ICopyrightMD5Service copyrightmd5Service;

	/* (non-Javadoc)
	 * @see org.springframework.security.web.authentication.AuthenticationSuccessHandler#onAuthenticationSuccess(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.springframework.security.core.Authentication)
	 */
	@SuppressWarnings("unchecked")
	@Transactional
	public void onAuthenticationSuccess(HttpServletRequest request,
			HttpServletResponse response, Authentication authentication)
			throws IOException, ServletException {
		/*if(ONLINENONTERMIANL == 0){
			try {
				ONLINENONTERMIANL = Integer.parseInt(registerInfo().get(8));//初始化技术员许可数量
			} catch (NumberFormatException e) {
				LOGGER.error("Initialization concurrence technician license number exception:/n"+e.getMessage());
			}
		}*/
		// 取得Session
		HttpSession session = ((HttpServletRequest) request).getSession();
		/*if (!isSafe(session) ) {//如果没有获取到这几个标识，说明修改了系统过滤器
			response.sendError(998);
			return;
		}*/
		String loginName = request.getParameter("j_requestUserName");
		String loginModel=request.getParameter("j_loginModel");
		String tenantId = TenantIdResolver.getInstance().getDefaultTenantId();
		if (!StringUtils.hasText(loginName)) {
			loginName = authentication.getName();
		}
		if (StringUtils.hasText(loginModel)) {
			loginModel = loginName+loginModel;
		}else{
			loginModel = loginName+"mobile";
		}
		
		ServletContext sctx = session.getServletContext();
		Map<String, HttpSession> sessionMap = null;
		Boolean same=false;//是否是相同的帐号和登录模式
		Boolean result=false;//是否是相同的帐号
		if (sctx != null) {
			sessionMap = (HashMap<String, HttpSession>) sctx.getAttribute("sessionMap");
			result=sameAccount(sessionMap, loginName, result);//是相同的帐号
			same=sameAccountAndLoginMode(sessionMap, loginModel,same);//是相同的帐号和登录模式
			//在别的地方登录，强迫下线
			sessionMap=forcedOffline(sessionMap, loginModel);
		} 
		if(sessionMap==null) {
			sessionMap = new HashMap<String, HttpSession>();
		}
		//登录成功后设置Session
		User user = userDAO.findUniqueBy("loginName",loginName.toLowerCase());
		if (user == null) {
			user = userDAO.findUniqueBy("loginName",loginName.toUpperCase());
		}
		//获取验证成功后的用户角色
		Authentication auth  = (Authentication) SecurityContextHolder.getContext().getAuthentication();
		List<GrantedAuthority> gas = (List<GrantedAuthority>)auth.getAuthorities();
		StringBuffer roleCode = new StringBuffer();
		for(GrantedAuthority ga : gas){
			roleCode.append(ga.getAuthority() + ",");
		}
		session = depositAnswer(user, session, tenantId,roleCode);
		// 记录用户登录
		onlineUserService.setOnlineUsersMap(tenantId, loginName, userInfoService.checkNonTerminal(loginName));
		//并发用户许可控制办法
		//Integer nonTerminal = (Integer) ((sctx!=null 
		//		&& sctx.getAttribute("nonTerminal") != null) ? sctx.getAttribute("nonTerminal") : 0);
		/*if(sctx!=null 
				&& userInfoService.checkNonTerminal(loginName)//判断是否是技术员
				//&& nonTerminal <= ONLINENONTERMIANL //判断当前并发用户是否小于或等于并发许可数
				&& !"admin".equalsIgnoreCase(loginName) && !result){//排除admin帐号为并发用户
			sctx.setAttribute("nonTerminal",++nonTerminal);
			LOGGER.debug("the num of technician plus 1 , the technician 's name is "+loginName);
		}*/
		//登录前的判断和跳转
		Jump(sessionMap, request, response, loginModel, loginName, user, roleCode, session,sctx);
	}
	/**
	 * 判断是否是相同帐号
	 * @param sessionMap
	 * @param loginName
	 * @param result
	 * @return
	 */
	@Transactional
	private Boolean sameAccount(Map<String, HttpSession> sessionMap,String loginName,Boolean result){
		String loginNormal=loginName+"normal";
		String loginMobile=loginName+"mobile";
		if (sessionMap!=null && (((loginNormal !=null && sessionMap.containsKey(loginNormal))
				|| (loginNormal !=null && sessionMap.containsKey(loginNormal.toLowerCase())) 
				|| (loginNormal !=null && sessionMap.containsKey(loginNormal.toUpperCase())))
				|| ((loginMobile !=null && sessionMap.containsKey(loginMobile))
				|| (loginMobile !=null && sessionMap.containsKey(loginMobile.toLowerCase())) 
				|| (loginMobile !=null && sessionMap.containsKey(loginMobile.toUpperCase()))))) {
			result=true;
		}
		return result;
	}
	/**
	 * 是相同的帐号和登录模式
	 * @param sessionMap
	 * @param loginModel
	 * @param same
	 * @return
	 */
	@Transactional
	private Boolean sameAccountAndLoginMode(Map<String, HttpSession> sessionMap,String loginModel,Boolean same){
		if (sessionMap!=null && ((loginModel !=null && sessionMap.containsKey(loginModel))
				|| (loginModel !=null && sessionMap.containsKey(loginModel.toLowerCase())) 
				|| (loginModel !=null && sessionMap.containsKey(loginModel.toUpperCase())))) {
			same=true;
		}
		return same;
	}
	/**
	 * 在别的地方登录，强迫下线
	 * @param sessionMap
	 * @param loginModel
	 * @param same
	 * @return
	 */
	@Transactional
	private Map<String, HttpSession> forcedOffline(Map<String, HttpSession> sessionMap,String loginModel){
		if (sessionMap!=null && ((loginModel !=null && sessionMap.containsKey(loginModel))
				|| (loginModel !=null && sessionMap.containsKey(loginModel.toLowerCase())) 
				|| (loginModel !=null && sessionMap.containsKey(loginModel.toUpperCase())))) {
			HttpSession oldSession = (HttpSession) sessionMap.get(loginModel.toLowerCase());
			if (oldSession == null) {
				oldSession = (HttpSession) sessionMap.get(loginModel.toUpperCase());
			}
			if (oldSession != null) {
				try {
					oldSession.invalidate();
					LOGGER.error("old session has been invalidata , and the loginName is "+loginModel);
				} catch (Exception e) {
					LOGGER.error("Session invalidate exception :/n"+e.getMessage());
				}
			}
			sessionMap.remove(loginModel);
		}
		return sessionMap;
	}
	/**
	 * 将用户信息存入Session
	 * @param user
	 * @param session
	 * @param tenantId
	 * @param roleCode
	 * @return
	 */
	@Transactional
	private HttpSession depositAnswer(User user,HttpSession session,String tenantId,StringBuffer roleCode){
		if (user != null) {
			session.setAttribute(SessionName.TENANTID.getName(), tenantId);
			// 基本信息
			session.setAttribute(SessionName.FULLNAME.getName(), user.getFullName());
			session.setAttribute(SessionName.USERID.getName(), user.getUserId());
			session.setAttribute(SessionName.LOGINNAME.getName(), user.getLoginName());
			// 工号
			session.setAttribute(SessionName.CALLCENTERUSER.getName(), user.getLcallCodeOper());
			session.setAttribute(SessionName.CALLCENTERHOST.getName(), user.getRemoteHost());
			session.setAttribute(SessionName.CALLCENTERPORT.getName(), user.getRemotePort());
			session.setAttribute(SessionName.USERCOST.getName(), user.getUserCost());
			session.setAttribute(SessionName.ENDUSERSTYLE.getName(), user.getEndUserStyle());
			//所属机构
			Organization org = user.getOrgnization();
			if (org != null) {
				session.setAttribute(SessionName.ORGNO.getName(), org.getOrgNo());
				session.setAttribute(SessionName.ORGNAME.getName(), org.getOrgName());
			}
			//所属技术组
			Set<Organization> bgs = user.getBelongsGroup();
			List<String> bgsList = new ArrayList<String>();
			List<String> bgNosList = new ArrayList<String>();
			for (Organization bg : bgs) {
				bgsList.add("Group_" + bg.getOrgNo());
				bgNosList.add(bg.getOrgNo().toString());
			}
			session.setAttribute(SessionName.TECHNOLOGYGROUPNO.getName(), bgNosList);
			session.setAttribute(SessionName.TECHNOLOGYGROUP.getName(), bgsList);
			
			//所属公司
			Organization company = organizationDAO.findById(user.getCompanyNo());
			if (company != null) {
				session.setAttribute(SessionName.COMPANYNO.getName(), user.getCompanyNo());
				session.setAttribute(SessionName.COMPANYNAME.getName(), company.getOrgName());
			}
			session.setAttribute(SessionName.ROLECODES.getName(), roleCode.toString());
			
			//查询最上层公司(机构)
			Organization topCompany = organizationDAO.findTopCompany();
			if (topCompany != null && topCompany.getOrgNo() != null) {
				session.setAttribute("topCompanyNo", topCompany.getOrgNo());
			}
		}
		return session;
	}
	/**
	 * 登录前的判断和跳转
	 * @param sessionMap
	 * @param nonTerminal
	 * @param request
	 * @param response
	 * @param loginModel
	 * @param loginName
	 * @param user
	 * @param roleCode
	 * @param session
	 * @throws IOException
	 * @throws ServletException
	 */
	@Transactional
	private void Jump(Map<String, HttpSession> sessionMap,HttpServletRequest request,
			HttpServletResponse response,String loginModel,String loginName,User user,StringBuffer roleCode
			,HttpSession session,ServletContext sctx) throws IOException, ServletException {
		/**
		 * 日志记录
		 * 用户并发异常时记录其日志
		 */
		/*if(ONLINENONTERMIANL!=0 && ONLINENONTERMIANL < nonTerminal){
			LOGGER.error("The number of logining user is over the limited!!!!!!!!!!!!!!!");
			LOGGER.error("The number of logining is "+nonTerminal);
			for(HttpSession se : sessionMap.values()){
				LOGGER.error("HttpSession is " + se);
			}
		}*/
		String url = request.getContextPath();
		//String copytight=copyrightmd5Service.JudgeMD5();
		
		/*if (activationOverdue == null || activationOverdue == false) {//是否激活
			session.invalidate();//清空会话
			url = url + "/pages/errors/notActivated.jsp";
		} else if (licenseOverdue == null || licenseOverdue == true) {//许可是否过期
			session.invalidate();//清空会话
			url = url + "/pages/errors/overdue.jsp";
		} else if (StringUtils.hasText(copytight) && copytight.equals("Error")) {//版权控制
			session.invalidate();//清空会话
			url = url + "/pages/errors/copyright.jsp";
		}else *//* else if(ONLINENONTERMIANL != 0 
				&& nonTerminal > ONLINENONTERMIANL 
				&& !"admin".equalsIgnoreCase(loginName)){//判断是否超出许可数量或者是否为管理员
			session.invalidate();//清空会话
			url = url + "/pages/login.jsp?overonlinenontermianl=true";
		}*/
		// 用户重新放入Map
		sessionMap.put(loginModel, session);
		if (sctx != null){
			sctx.setAttribute("sessionMap", sessionMap);
		}
		if ("EndUserWeb".equals(loginModel)){
			url = url + "/tickets/index.jsp";
		}else if(loginModel.indexOf("wap")>-1){
			url=url+"/wap/index.jsp";
		}else {
			
			/*if(roleCode.toString().equals("ROLE_ENDUSER,")){
				if(StringUtils.hasText(user.getEndUserStyle())&&user.getEndUserStyle().equals("Simple")){//如果选择了简洁页面 
					url = url + "/tickets/index.jsp";
				}else if(StringUtils.hasText(user.getEndUserStyle())&&user.getEndUserStyle().equals("Classical")){//选择了古典样式
					url = url + "/pages/index.jsp";
				}else{//没有选择
					url = url + "/pages/endUser.jsp";
				}
			}else{*/
			   url = url + "/pages/index.jsp";
			//}
			
		}
		response.sendRedirect(url);
	}
	
	
	
	
	/**
	 * 对字符串进行解密.
	 * 
	 * @param str
	 * @return 解密后的字符.
	 * @throws Exception
	 */
	@SuppressWarnings("unused")
	private  String getDecode(String str) throws Exception {

		BASE64Decoder bd = new BASE64Decoder();
		byte[] bt = bd.decodeBuffer(str);
		return new String(bt);
	}
	

	@SuppressWarnings("unused")
	private boolean isSafe(HttpSession session){
		return true 
				&& session.getAttribute("Copyright") != null
				&& session.getAttribute("RegisterFilter") != null 
				&& session.getAttribute("ActivationFilter") != null 
				;
	}
}
